package com.lance.answer.question_answer.xj_new;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lance.answer.dto.CompleteInfo;
import com.lance.answer.dto.CourseInfo;
import com.lance.answer.dto.XjCourseVideoInfo;
import com.lance.answer.dto.XjUserCourseInfo;
import com.lance.answer.gui.answer.AnswerObject;
import com.lance.answer.gui.answer.DealJsonString;
import com.lance.answer.gui.answer.Util;
import com.lance.answer.util.Constant;
import com.lance.answer.util.HttpUtil;
import com.lance.answer.util.XinJiangUtil;
import javafx.concurrent.Task;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 * @author fengx
 * 新疆一体化答题-课程作业
 *
 * <p>
 * "questionTitle":"一般较为常见的职业发展路径有两条：##和##。",
 * "questionTitle":"一般较为常见的职业发展路径有两条：和。",
 * 答案中不能出现##号，要替换一下。
 * </p>
 */
@Slf4j
public class DoXJAnswerHomeworkTask extends Thread {

    private String driverPath;
    private LinkedBlockingDeque<CourseInfo> userCourses;

    public DoXJAnswerHomeworkTask(String driverPath, LinkedBlockingDeque<CourseInfo> userCourses) {
      this.driverPath = driverPath;
      this.userCourses = userCourses;
    }


    @SneakyThrows
    @Override
    public void run() {

        while (userCourses.size() > 0) {
            CourseInfo courseInfo = userCourses.take();
            String userName = courseInfo.getUser();
            String password = courseInfo.getPwd();
            String subjectName = courseInfo.getSubjectName();
            int openCourseId = courseInfo.getOpenCourseId();
            Map<String, AnswerObject> answerMap = courseInfo.getAnswerMap();
            log.info("任务：{} 剩余 {} 行，当前课程：{} 用户名：{} 密码：{}",
                    Thread.currentThread().getName(),userCourses.size(),subjectName,userName, password);
            completeHomework(subjectName, openCourseId, answerMap, userName, password);
            //log.info("{} 开始执行刷题任务",Thread.currentThread().getName());

        }

        if (userCourses.size() == 0) {
            log.info("课程所有用户均已执行完毕，系统将在20min后结束");
            TimeUnit.MINUTES.sleep(20);
            return;
        }
    }

    private static List<WebElement> findWeElements(WebDriver driver, String cssSelector, int second) {
        return (new WebDriverWait(driver, Duration.ofSeconds(second))).until((ExpectedCondition<List<WebElement>>)
                d -> {
                    assert d != null;
                    return d.findElements(By.cssSelector(cssSelector));
                });
    }


    public static void completeHomework(String majorName, int openCourseId, Map<String, AnswerObject> answerMap,
                                        String username, String pwd) {


        boolean isComplete = false;
        try {




            File directory = new File("E:\\answerInfo一体化\\" + majorName);
            if (!directory.exists()) {
                directory.mkdirs();
            }

            String filePath = "E:\\answerInfo一体化\\" + majorName + "\\" + username + "-homework.txt";
            File userCompleteInfoFile = new File(filePath);
            InputStream inputStream = new FileInputStream(userCompleteInfoFile);
            String completeInfoStr = IOUtils.toString(inputStream, "UTF-8");
            List<CompleteInfo> completeInfoList = JSONObject.parseArray(completeInfoStr, CompleteInfo.class);
            if (null != completeInfoList) {
                for (CompleteInfo info : completeInfoList) {
                    if ("没有这门课程！".equals(info.getSummary()) || "完成了这门课程！".equals(info.getSummary())||"该课程没有平时作业！".equals(info.getSummary())) {
                //   if ("完成了这门课程！".equals(info.getSummary())) {
                        isComplete = true;
                        break;
                    }
                    // 临时开放
//                    if ("完成了这门课程！".equals(info.getSummary())) {
//                        isComplete = true;
//                        break;
//                    }
                }
            }
        } catch (Exception e) {
           // e.printStackTrace();
        }
        if (isComplete) {
            return;
        }


        WebDriver driver = Util.getDriver("c:\\ynouAutoStudy\\chromedriver.exe");

        try {
            int sid = 0;
            driver.get("https://xjskk.open.com.cn/stuspace-auth/#/login");
            XinJiangUtil.studentLogin(driver, username, pwd);
            Thread.sleep(3000);
         //   Thread.sleep(60000);

            try {
                WebElement we = findWeElements(driver, "div[class='part']", 20).get(0);
                // FIXME 正式要删掉
                String title = we.getAttribute("title");
                LinkedList<String> list = Lists.newLinkedList();
                list.add("2022年秋季");
                list.add("2022秋季");
                list.add("2022年春季");
                list.add("2022春季");
                list.add("2021年秋季");
                list.add("2021秋季");
                list.add("2021年春季");
                list.add("2021春季");
                list.add("2020年秋季");
                list.add("2020秋季");
                list.add("2020年春季");
                list.add("2020春季");
                list.add("2019年秋季");
                list.add("2019秋季");
                list.add("2019年春季");
                list.add("2019春季");
                for (String s : list) {
                    if (title.contains(s)) {
                        we.click();
                        break;
                    }
                }
            } catch (Exception e1) {
                log.info("用户：{}登录发生错误",username);
            }
            Thread.sleep(2000);


//            // FIXME 有的人报了多个专业

            Set<Cookie> cookies = driver.manage().getCookies();
            String studentSpaceProfile = Util.getStudentSpaceProfile2(cookies);
            String authorization = Util.getAuthorization2(cookies);
            Map<String, String> heads = Maps.newHashMap();
            String cookie = Util.getCookie(cookies);
            initHeads(heads, studentSpaceProfile, authorization);

            String getCourseInfoUrl = "https://xjskk.open.com.cn/api/student/student-space-service/courses/" +
                    "getStudentCourses?pageNumber=1&pageSize=2000000&status=1&courseNameCode=";
            XjUserCourseInfo userCourseInfo = JSON.parseObject(HttpUtil.get(getCourseInfoUrl, cookie, heads),
                    XjUserCourseInfo.class);
            for (XjUserCourseInfo.ContentDTO.ItemsDTO items : userCourseInfo.getContent().getItems()) {
                if (openCourseId == items.getOpenCourseId()) {
                    sid = items.getSelectCourseId();
                    break;
                }
            }

            driver.get("https://xjskk.open.com.cn/stuspace/#/course?oId=" + openCourseId + "&sId=" + sid);

            // 获取当前已经刷了的课程项目

            Thread.sleep(5000);
            for (WebElement liWe : findWeElements(driver, "li[class='fl']", 30)) {
                if ("课程作业".equals(liWe.getText().trim())) {
                    liWe.click();
                    break;
                }
            }
            Thread.sleep(5000);

//            try {
//                WebElement loadingWebElement =  Util.findByClassName(driver,"to-loading");
//                if(loadingWebElement!=null&&"没有更多数据".equals(loadingWebElement.getText().trim())){
//                    List<CompleteInfo> completeInfoList = Lists.newArrayList();
//                    CompleteInfo info = new CompleteInfo();
//                    info.setSummary("该课程没有平时作业！");
//                    completeInfoList.add(info);
//                    FileUtils.write(new File("E:\\answerInfo一体化\\" + majorName + "\\" + username + "-homework.txt"), JSONObject.toJSONString(completeInfoList, SerializerFeature.PrettyFormat), "utf-8");
//                    Thread.sleep(2000);
//                    closeDriver(driver);
//                    return;
//                }
//            }catch (Exception e){
//
//            }


            //FIXME =========================================

            //   WebElement webElement = Util.findByClassName(driver, "status-2");
            List<WebElement> status = Lists.newArrayList();
            status.addAll(driver.findElements(By.className("status-2")));
            status.addAll(driver.findElements(By.className("status-4")));
            // 已批阅
            int hasDone = 0;
            int iii = 0;
            for (WebElement webElement : status) {
                if (webElement != null && webElement.getText().equals("已提交未批阅")) {
                    iii++;
                }
                if (webElement != null && webElement.getText().equals("已批阅")) {
                    hasDone++;
                    iii++;
                }
            }

            // ==4说明就OK了
            if (iii == 4 || (openCourseId == 38411&&iii== 1)) {
                //    System.err.println("1111111111111111111111111完成了这门课程");
                List<CompleteInfo> completeInfoList = Lists.newArrayList();

                CompleteInfo info = new CompleteInfo();
                info.setSummary("完成了这门课程！");
                completeInfoList.add(info);
                FileUtils.write(new File("E:\\answerInfo一体化\\" + majorName + "\\" + username + "-homework.txt"),
                        JSONObject.toJSONString(completeInfoList, SerializerFeature.PrettyFormat), "utf-8");
                try {
                    driver.close();
                    driver.quit();
                } catch (Exception ee) {

                }
                // 完成了！
                return;
            }

            //FIXME =========================================


            // v-btn theme--light primary

        // 2021-12-20   int homeworkSize = findWeElements(driver, "button[class='v-btn theme--light primary']", 30).size();

            int homeworkSize = driver.findElement(By.className("work-part1")).findElements(By.className("text")).size();

            if(homeworkSize == 0){

                List<CompleteInfo> completeInfoList = Lists.newArrayList();
                CompleteInfo info = new CompleteInfo();
                info.setSummary("该课程没有平时作业！");
                completeInfoList.add(info);
                FileUtils.write(new File("E:\\answerInfo一体化\\" + majorName + "\\" + username + "-homework.txt"),
                        JSONObject.toJSONString(completeInfoList, SerializerFeature.PrettyFormat), "utf-8");
                try {
                    driver.close();
                    driver.quit();
                } catch (Exception ee) {

                }
            }

            boolean refresh = false;
            for (int i = 0; i < homeworkSize; i++) {

                if (i > 0 && refresh) {
                    driver.navigate().refresh();
                    Thread.sleep(3000);
                    for (WebElement liWe : findWeElements(driver, "li[class='fl']", 30)) {
                        if ("课程作业".equals(liWe.getText().trim())) {
                            liWe.click();
                            break;
                        }
                    }
                    Thread.sleep(10000);
                }


                boolean isCommit = false;
                // todo 校验
                try {

                    List<WebElement> textAreaList = driver.findElement(By.className("work-part1")).findElements(By.className("text"));
                    WebElement textArea = textAreaList.get(i);
                    WebElement webElement = Util.findByClassName(textArea, "status-2");
                    if (webElement != null && webElement.getText().equals("已提交未批阅")) {
                        isCommit = true;
                    }
                    WebElement webElement2 = Util.findByClassName(textArea, "status-4");
                    if (webElement2 != null && webElement2.getText().equals("已批阅")) {
                        isCommit = true;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (isCommit) {
                    refresh = false;
                    continue;
                }
                refresh = true;


                // 这里点击按钮时要有一个鼠标下拉的操作，不然点击不到答题
//                if (i > 2) {
//                    ((JavascriptExecutor) driver).executeScript("window.scrollTo(0,100000)");
//                }
          //      WebElement btnWe = findWeElements(driver, "button[class='v-btn theme--light primary']", 30).get(i);
             // 2021-12-20   WebElement btnWe = findWeElements(driver, "button[class='v-btn theme--light primary']", 30).get(i);
                WebElement btnWe = driver.findElement(By.className("work-part1")).findElements(By.className("text"))
                        .get(i).findElement(By.cssSelector("button[class='v-btn theme--light primary']"));
                Thread.sleep(1000);
                // TODO 开始答题
                btnWe.click();
                Util.switchToLast(driver);
                Thread.sleep(5000);
                // 2、确定答题
                confirmAnswer(driver);
                Thread.sleep(5000);
                // 3、开始答题 TODO list-children-class children-div-top
                List<WebElement> questionWeList = findWeElements(driver, "div[class^='list-children-class']", 20);

                driver.manage().window().maximize();
                doAnswer(driver, questionWeList, answerMap);
                // FIXME TODO 要提交答案
                // 4、提交测验
                Thread.sleep(3000);
                btnClick(driver, "提交作业");
                Thread.sleep(4000);
                btnClick(driver, "确定");
                Thread.sleep(3000);
                // 答题完成后返回课程目录
                // btnClick(driver, "返回列表");
                Thread.sleep(3000);
                driver.close();
                Thread.sleep(2000);
                Util.switchToFirst(driver);
                Thread.sleep(5000);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("Exception：username:{}  pwd:{}",username,pwd);
            System.err.println("Exception !!!!!!!!!!!!!!!!!");
        } finally {
            try {
                driver.close();
                driver.quit();
            } catch (Exception e) {

            }
        }
    }

    public static void btnClick(WebDriver driver, String btnName) {
        for (WebElement confirmBtn : driver.findElements(By.cssSelector("button[type='button']"))) {
            if (confirmBtn.getText().equals(btnName)) {
                confirmBtn.click();
                break;
            }
        }
    }


    private static void doAnswer(WebDriver driver, List<WebElement> questionWeList, Map<String, AnswerObject> answerMap) throws Exception {

        // fixme
        Thread.sleep(1000);
        // fixme

        //   System.err.println("questionWeListSize：" + questionWeList.size());

        Map<String, Integer> ueditorIndexMap = Maps.newHashMap();
        ueditorIndexMap.put("ueditorIndex", 0);
        for (WebElement questionWe : questionWeList) {
            WebElement titleWe = questionWe.findElement(By.className("children-value-class"));
            // fixme
            String title = titleWe.getText();
            title = Util.dealContent(title);
            title = DealJsonString.delHTMLTag(title);
            if(Strings.isNullOrEmpty(title)){
                continue;
            }
            System.err.println("title:"+title);
            System.err.println("answerMap:"+JSON.toJSONString(answerMap));
            AnswerObject answerObject = answerMap.get(title);
            if (answerObject == null) {
                //   System.err.println("答案不存在:" + title);
                // FIXME 如果问题不存在，就用HANLP来匹配
                double similarity = 0.0;
                String answerTitle = "";
                for (Map.Entry<String, AnswerObject> entry : answerMap.entrySet()) {
                    double k1 = DealJsonString.getSimilarity(title, entry.getKey());
                    if (k1 > similarity) {
                        similarity = k1;
                        answerTitle = entry.getKey();
                    }
                }
                //    System.err.println("answerTitle:" + answerTitle + " similarity:" + similarity);
                // 相似度为0.9 就选择
                if (similarity > 0.60) {
                    answerObject = answerMap.get(answerTitle);
                } else {
                    try {
                        Thread.sleep(200);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            //     System.err.println("answerObject:" + JSONObject.toJSONString(answerObject));
            if(null == answerObject){
                return;
            }
            String questionType = answerObject.getQuestionType();


            switch (questionType) {
                case "1":
                case "2":
                case "3":
                case "5": { //阅读理解
                    // 单选 多选 判断
                    doChoiceExercise(questionWe, answerObject.getAnswers());
                    break;
                }
                case "4":
                case "6": {
                    doGapFilling(driver, questionWe, answerObject.getAnswers(), ueditorIndexMap);
                    break;
                }
                default: {

                    // 汉语综合技能  、阅读理解 （共2题，共10
                    System.err.println("answerObject:::"+answerObject);
                    throw new Exception("不支持的题型!" + questionType + answerObject.getQuestionTitle());
                }
            }
        }
    }

    /**
     * 填空题
     *
     * @param answerElement answerElement
     * @param realAnswers   realAnswers
     */
    private static void doGapFilling(WebDriver driver, WebElement answerElement, List<String> realAnswers,
                                     Map<String, Integer> ueditorIndexMap) {

        try {
            List<WebElement> divList = answerElement.findElements(By.cssSelector("div[class='virtualInput']"));
            //   System.err.println("divList：Size:" + divList.size());
            for (int i = 0; i < divList.size(); i++) {
                WebElement div = divList.get(i);
                //   input.clear();
                div.click();
                Thread.sleep(2000);
                //  WebElement iframe = driver.findElement(By.id("ueditor_0"));
                Integer index = ueditorIndexMap.get("ueditorIndex");
                WebElement iframe = driver.findElement(By.id("ueditor_" + index));
                //   System.err.println("realAnswers.get(i):" + realAnswers.get(i));
                String js = "document.getElementById('" + iframe.getAttribute("id") + "').contentWindow.document.body.innerText = '" + realAnswers.get(i) + "'";
                ((JavascriptExecutor) driver).executeScript(js);
                ueditorIndexMap.put("ueditorIndex", ++index);
                //  Thread.sleep(200000);
                //  div.sendKeys( realAnswers.get(i));
                Thread.sleep(2000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private static void doChoiceExercise(WebElement answerElement, List<String> realAnswers) {


        try{
            Random random = new Random();
            // 6%的几率任意选
            if(random.nextInt(100)<6){
                answerElement.findElements(By.cssSelector("div[class='clearfix']")).get(0)
                        .findElement(By.cssSelector("span[class^='el-']")).click();
                return;
            }
        }catch (Exception e){
            e.printStackTrace();
        }


        // 遍历题目的每一个选项
        for (WebElement singleAnswerElement : answerElement.findElements(By.cssSelector("div[class='clearfix']"))) {
            String answerContent = singleAnswerElement.
                    findElement(By.cssSelector("span[class='option-value-class']")).getText();
            //兼容特殊字符
            answerContent = Util.dealContent(answerContent);
            //   System.err.println("answerContent:" + answerContent);
            // 找到单选框或复选框
            // el-checkbox el-radio
            WebElement labelElement = singleAnswerElement.findElement(By.cssSelector("label[class^='el-']"));

            // 找到真正的点击按钮 el-radio__input el-checkbox__input
            WebElement realClickElement = singleAnswerElement.findElement(By.cssSelector("span[class^='el-']"));

            String labelClass = labelElement.getAttribute("class");
            //   System.err.println("labelClass:" + labelClass);

            // 单选或者判断题
            WebElement clickWebElement = null;
            if (labelClass.contains("radio")) {
                clickWebElement = labelElement.findElement(By.cssSelector("input[type='radio']"));
            }
            if (labelClass.contains("checkbox")) {
                clickWebElement = labelElement.findElement(By.cssSelector("input[type='checkbox']"));
            }
            // FIXME 判断题0：对 1：错
            // 这里的ID是每个选项的ID answerContent是每个选项的内容
            for (String realAnswer : realAnswers) {
                //     System.err.println("origin:" + answerContent);
                // if (answerContent.equals(realAnswer)) {
                if (DealJsonString.delHTMLTag(answerContent).equals(DealJsonString.delHTMLTag(realAnswer))) {
                    //       System.err.println("realAnswer:" + realAnswer);
                    assert clickWebElement != null;
                    if (!clickWebElement.isSelected()) {
                        realClickElement.click();
                    }
                }
            }


        }
    }


    public static void initHeads(Map<String, String> heads, String studentSpaceProfile, String authorization) {
        heads.put("referer", "https://xjskk.open.com.cn/stuspace/");
        heads.put("authority", "xjskk.open.com.cn");
        heads.put("path", "/api/student/student-space-service/resources/updateResourceTrace");
        heads.put("scheme", "scheme");
        heads.put("open-student-space-profile", studentSpaceProfile);
        heads.put("origin", "https://xjskk.open.com.cn");
        heads.put("authorization", authorization);
    }

    public static JSONObject initSaveJson(int openCourseId, XjCourseVideoInfo.ContentDTO.ResourcesDTO resources) {
        JSONObject saveJson = new JSONObject();
        // 课程ID，固定的
        saveJson.put("openCourseId", openCourseId);
        // 单个视频的资源ID
        saveJson.put("resourceUid", resources.getResourceUid());
        // 视频总时长
        saveJson.put("totalTime", resources.getTraceTime());
        saveJson.put("traceTime", 0);
        return saveJson;
    }


    public static void clickAnswer(WebDriver driver, XjCourseVideoInfo.ContentDTO.ExaminesDTO examines) {
        // fixme 按理说应该只选择最后一个答题
        for (WebElement span : findWeElements(driver, "span[class='testName font-blue']", 20)) {
            if (span == null || Strings.isNullOrEmpty(span.getText())) {
                continue;
            }
            //    System.err.println("span:" + span.getText());
            // if (span.getText().trim().equals(examines.getName().trim())) {
            if (DealJsonString.delHTMLTag(span.getText()).equals(DealJsonString.delHTMLTag(examines.getName()))) {
                // 点击完成之后要break
                span.click();
                break;
            }
        }
    }

    public static void confirmAnswer(WebDriver driver) {
        List<WebElement> saveButtons = findWeElements(driver, "button[type='button']", 30);
        if (!CollectionUtils.isEmpty(saveButtons)) {
            for (WebElement webElement : saveButtons) {
                String text = webElement.getText();
                //     System.err.println("text:" + text);
                if (text.contains("确 定")) {
                    webElement.click();
                    break;
                }
            }
        }
    }

    private static void closeDriver(WebDriver driver) {
        try {
            driver.close();
            driver.quit();
        } catch (Exception e) {

        }
    }

}
